package com.wc.fortnight_blue_bridge.Q16模拟二.I_前缀和;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.StringTokenizer;

/**
 * @Author congge
 * @Date 2024/11/23 22:37
 * @description
 * https://dasai.lanqiao.cn/pages/v7/dasai/prelim/prelim_examing.html?examUsperPaperId=338843&applyId=579285787961
 */
public class Main {
    /**
     * 【问题描述】
     * 小蓝有一个 n 行 m 列的矩阵 a[i][j] ，他想在矩阵中找出一个“口”字形状的区域，使得区域上的值的和最大。
     * 具体讲，一个“口”字形状的区域可以由两个坐标 (x1, y1) 和 (x2, y2) 确定，满足：
     * 1 <= x1 < x2 <= n ；
     * 1 <= y1 < y2 <= m ；
     * x2 - x1 = y2 - y1 。
     *
     * 对应的区域由满足以下条件之一的点 (x, y) 构成：
     * x1 <= x <= x2，且 y = y1 ，对应“口”的左边一竖；
     * y1 <= y <= y2，且 x = x1 ，对应“口”的上面一横；
     * x1 <= x <= x2，且 y = y2 ，对应“口”的右边一竖；
     * y1 <= y <= y2，且 x = x2 ，对应“口”的下面一横。
     * 请注意有些点满足以上条件的多个，例如左上角的点 (x1, y1) ，在计算时算为一个点。
     *
     * 区域上的值是指对应区域的所有点的值，即“口”字的框上的值，不含框内和框外的值。
     *
     * 【输入格式】
     * 输入的第一行包含两个整数 n, m ，分别表示行数和列数。
     *
     * 接下来 n 行，每行包含 m 个整数，相邻数之间使用一个空格分隔，依次表示矩阵的每行每列的值，本部分的第 i 行第 j 列表示 a[i][j] 。
     *
     * 【输出格式】
     * 输出一行包含一个整数，表示最大的和。
     *
     * 【样例输入】
     * 5 6
     * 1 -1 2 -2 3 -3
     * -1 2 -2 3 -3 4
     * 2 -2 3 -3 4 -4
     * -2 3 -3 4 -4 5
     * 3 -3 4 -4 5 -5
     * 【样例输出】
     * 4
     * 【样例说明】
     * 取 (x1, y1) = (1, 1) ， (x2, y2) = (5, 5) 可得到最大值。
     *
     * 【评测用例规模与约定】
     * 对于 30% 的评测用例，1 <= n, m <= 30 ，-1000 <= a[i][j] <= 1000 。
     * 对于 60% 的评测用例，1 <= n, m <= 100 ，-1000 <= a[i][j] <= 1000 。
     * 对于所有评测用例，1 <= n, m <= 300 ，-1000 <= a[i][j] <= 1000 。
     */
    static FastReader sc = new FastReader();
    static PrintWriter out = new PrintWriter(System.out);
    static int N = 310;
    static int[][] a = new int[N][N];
    static int[][] rows = new int[N][N], cols = new int[N][N];
    static int n, m;

    public static void main(String[] args) {
        n = sc.nextInt();
        m = sc.nextInt();

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                a[i][j] = sc.nextInt();
            }
        }

        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++){
                rows[i][j] = rows[i][j - 1] + a[i][j];
                cols[i][j] = cols[i - 1][j] + a[i][j];
            }
        }

        int res = (int) (-1e8);
        for (int len = 2; len <= Math.min(n, m); len++) {
            for (int i = 1; i <= n; i++) {
                if (i + len - 1 > n) break;
                for (int j = 1; j <= m; j++) {
                    if (j + len - 1 > m) break;
                    int sum = 0;
                    // 上
                    sum += rows[i][j + len - 1] - rows[i][j - 1];
                    // 下
                    sum += rows[i + len - 1][j + len - 1] - rows[i + len - 1][j - 1];
                    // 左
                    sum += cols[i + len - 2][j] - cols[i][j];
                    // 右
                    sum += cols[i + len - 2][j + len - 1] - cols[i][j + len - 1];
                    res = Math.max(sum, res);
                }
            }
        }
        out.println(res);
        out.flush();
    }
}

class FastReader {
    StringTokenizer st;
    BufferedReader br;

    FastReader() {
        br = new BufferedReader(new InputStreamReader(System.in));
    }

    String next() {
        while (st == null || !st.hasMoreElements()) {
            try {
                st = new StringTokenizer(br.readLine());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return st.nextToken();
    }

    int nextInt() {
        return Integer.parseInt(next());
    }

    String nextLine() {
        String s = "";
        try {
            s = br.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return s;
    }

    long nextLong() {
        return Long.parseLong(next());
    }

    double nextDouble() {
        return Double.parseDouble(next());
    }

    // 是否由下一个
    boolean hasNext() {
        while (st == null || !st.hasMoreTokens()) {
            try {
                String line = br.readLine();
                if (line == null)
                    return false;
                st = new StringTokenizer(line);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return true;
    }
}

